package com.czy.facecompare.service.impl;

import com.czy.facecompare.service.FaceCompare;
import org.opencv.core.*;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import org.opencv.objdetect.CascadeClassifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import java.util.Arrays;

import static org.opencv.imgproc.Imgproc.CV_COMP_CORREL;

/**
 * 人脸识别相识度类
 */

@Service
public class FaceCompareImpl implements FaceCompare {

    // 初始化人脸探测器
    private CascadeClassifier faceDetector;

    // 静态代码块当类被加载的时候会优先执行此代码
//    static {
//
//        // 取resources得路径
//        String resourcePath = FaceCompare.class.getClass().getResource("/").getPath();
//        // 取消盘符开头的 / 线
//        resourcePath = resourcePath.substring(1);
//        // 拼接Dll位置 路径不能包含中文
//        String opencvDllName = resourcePath + "lib/opencv_java452.dll";
//        System.out.println(opencvDllName);
//
//        // 拼接xml文件路径 xml路径不能包含中文
//        String faceXML = resourcePath + "lib/haarcascade_frontalface_alt.xml";
//        System.out.println(faceXML);
//
//    }


    // 文件DLL存储路径
    private static final String opencvDllName = "d:/lib/opencv_java452.dll";

    // 文件xml存放路径
    private static final String faceXML = "d:/lib/haarcascade_frontalface_alt.xml";

    public FaceCompareImpl() {
        // 加载DLL文件
        System.load(opencvDllName);
        // 赋值人脸探测器
        faceDetector = new CascadeClassifier(faceXML);
    }

    // 灰度化人脸
    private Mat conv_Mat(String img) throws CvException {
        // 读取照片到矩阵
        Mat image0 = Imgcodecs.imread(img);
        Mat image1 = new Mat();
        // 灰度化
        Imgproc.cvtColor(image0, image1, Imgproc.COLOR_BGR2GRAY);
        // 探测人脸
        MatOfRect faceDetections = new MatOfRect();
        faceDetector.detectMultiScale(image1, faceDetections);
        // rect中人脸图片的范围
        for (Rect rect : faceDetections.toArray()) {
            Mat face = new Mat(image1, rect);
            return face;
        }
        // 没有检测到返回空
        return null;
    }

    /**
     * 照片对比
     * @param img_1     图片1的图片路径
     * @param img_2     图片1的图片路径
     * @param accuracy  对比的精度值 值越大匹配越精确 (越慢) 10000000
     * @return
     */
    @Override
    public double compare_image(String img_1, String img_2, int accuracy) throws CvException {

        Mat mat_1 = null;
        Mat mat_2 = null;
        try{
            // 灰度化处理,对人脸的局部识别
            mat_1 = conv_Mat(img_1);
            mat_2 = conv_Mat(img_2);
        }catch (CvException e){
            System.err.println("图片灰度处理异常,请更换图片");
            e.printStackTrace();
        }

        // 检测判断
        if (mat_1 == null) {
            System.out.println("图一没有检测到人脸特征");
            return 0.0;
        } else if (mat_2 == null){
            System.out.println("图二没有检测到人脸特征");
            return 0.0;
        }

        Mat hist_1 = new Mat();
        Mat hist_2 = new Mat();

        // 颜色范围
        MatOfFloat ranges = new MatOfFloat(0f, 256f);
        // 直方图大小， accuracy的值越大匹配越精确 (越慢) 10000000
        MatOfInt histSize = new MatOfInt(accuracy);
        Imgproc.calcHist(Arrays.asList(mat_1), new MatOfInt(0), new Mat(), hist_1, histSize, ranges);
        Imgproc.calcHist(Arrays.asList(mat_2), new MatOfInt(0), new Mat(), hist_2, histSize, ranges);

        // CORREL 相关系数
        return Imgproc.compareHist(hist_1, hist_2, CV_COMP_CORREL);
    }
}
